package org.arl.modem.transportARQ;

import java.util.Arrays;
import java.util.TreeMap;

import org.arl.modem.codec.CodecPacket;
import org.arl.modem.codec.Decoder;
import org.arl.modem.codec.LTDecoder;
import org.arl.modem.codec.LTKentMapDecoder;
import org.arl.modem.codec.RLFountainDecoder;

public class RXHelper {
   private int totalPackets;
   TreeMap<Integer, byte[]> rxTree;
   private int packetSize;
   private Decoder decode;

   // public RsOfgRlDecoder decode;

   public RXHelper(int totalPackets, int packetSize, int totalBytes) {
      this.totalPackets = totalPackets;
      System.out.println("packet size:" + packetSize);
      this.packetSize = packetSize;
      this.rxTree = new TreeMap<Integer, byte[]>();
      if (TransportARQ.ARQ_TYPE == 3) {
         System.out.println("Decode parameters:" + totalBytes + ":"
               + packetSize + ":" + 0);
         switch (TransportARQ.RATELESS_CODING_TYPE) {
         case 0:
            decode = new LTKentMapDecoder(totalBytes, packetSize, (float) 0.7);
            break;
         case 1:
            decode = new LTDecoder(totalBytes, packetSize);
            break;
         case 2:
            decode = new RLFountainDecoder(totalBytes, packetSize);
            break;
         default:
            break;
         }

      }
   }

   public int addRXPacket(TransportPacket tp) {
      if (TransportARQ.ARQ_TYPE == 3) {
         // writeToChannel(tp);
         decode.DecodingSuccessful();
         decode.decodeMessage(new CodecPacket(tp.messageData.clone(), tp.seed,
               tp.degree));
         // System.out.println("decoding by rateless finished");
      } else {
         if (tp.messageType == 0) {
            if (tp.packetId != 255) {
               System.out.println("msg size:" + tp.messageData.length);
               this.rxTree.put(tp.packetId, tp.messageData.clone());
            }
         }
      }
      System.out.println("RX tree size=" + rxTree.size());
      // log.fine("RX tree size=" + rxTree.size());
      return rxTree.size();
   }

   public boolean checkIFComplete() {
      if (TransportARQ.ARQ_TYPE == 3) {
         return decode.DecodingSuccessful();

      } else {
         if (rxTree.size() >= totalPackets) {
            // FIXME Rohit, Jan 16, 2012:if actual number of packets are 1-13
            // then
            // truncate the dummy packets after 13
            return true;
         } else {
            return false;
         }
      }
   }

   public byte[] getRxDataAsBytes() {
      int len = packetSize * totalPackets;
      byte[] data1 = new byte[len];

      Arrays.fill(data1, (byte) 0);
      if (TransportARQ.ARQ_TYPE != 3) {
         System.out.println("len:" + len + "  tree size:" + rxTree.size());
         int j = 0;
         for (byte[] pkt : rxTree.values()) {
            for (int i = 0; i < pkt.length; i++) {
               // System.out.println(i + ":" + j);
               data1[j] = pkt[i];
               j++;
            }
         }
         return data1;
      } else {
         return decode.getData();
      }
   }

   public String getRXDataAsString() {
      StringBuilder sb = new StringBuilder();
      StringBuilder temp = new StringBuilder();
      String hex = getRxDataAsBytes().toString();
      for (int i = 0; i < hex.length() - 1; i += 2) {
         // grab the hex in pairs
         String output = hex.substring(i, (i + 2));
         // convert hex to decimal
         int decimal = Integer.parseInt(output, 16);
         // convert the decimal to character
         sb.append((char) decimal);
         temp.append(decimal);
      }
      return sb.toString();
   }

   public int getTotalPackets() {
      return totalPackets;
   }
}
